#ifndef _DOMAIN_
#define _DOMAIN_

#include "Point.h"
#include <cassert>
/**
 * @brief Domain:定义域类
 * 
 * @tparam int DIM [维度]
 */
template <unsigned int DIM>
class Domain
{
public:
    /**
     * @brief 默认构造函数
     */
    Domain() = default;
    /**
     * @brief 默认析构函数
     */
    virtual ~Domain() = default;
    /**
     * @brief 含参构造函数
     *
     * @param _vertexList 定义域边界的顶点，以逆时针顺序给出
     */
    Domain(std::vector<Point<DIM>>& _vertexList) : vertexList{_vertexList} {};
    /**
     * @brief 设置定义域边界的顶点
     * 
     * @param _vertexList 定义域边界的顶点，以逆时针顺序给出
     */
    virtual void setVertexList(std::vector<Point<DIM>> &_vertexList){vertexList = _vertexList;};
    virtual vector<Point<2>>& getVertexList(){return vertexList;}
    virtual void setVertex(int _i, const Point<DIM>& _vertex){vertexList[_i] = _vertex;}
    /**
     * @brief 获取定义域边界第i个顶点
     * 
     * @param _i 以逆时针顺序，顶点的下标
     * @return 第i个顶点
     */
    virtual Point<DIM>& getVertex(int _i){return vertexList[_i];};

protected: 
    std::vector<Point<DIM>> vertexList;/*< 定义域的边界顶点*/
};

/**
 * @file   Domain.h
 * @author AOM
 * @date   Sat Mar  4 10:07:27 2023
 * 
 * @brief  边界结构体，处理D氏边界条件
 * 
 * 
 */

template <unsigned int DIM>
struct Boundary
{
    std::vector<Point<DIM> > _segementpointlist;
    bool is_on_boundary(Point<DIM> point);
    void setsegment(std::vector<Point<DIM>> temp){_segementpointlist = temp;};
    Boundary(){};
    Boundary(std::vector<Point<DIM>> temp){_segementpointlist = temp;};
};

template<>
bool Boundary<2>::is_on_boundary(Point<2> point)
{
    double x1 = _segementpointlist[0][0];
    double y1 = _segementpointlist[0][1];
    double x2 = _segementpointlist[1][0];
    double y2 = _segementpointlist[1][1];
    double x = point[0];
    double y = point[1];
    if(x1 > x2)//按照x从小到大
    {
        std::swap(x1,x2);
        std::swap(y1,y2);
    }
    bool ans = false;
    if(y1 == y2)
    {
        if(x >= x1 && x <= x2)
            ans = (y == y1);    
    }
    else if(x1 == x2)
    {
        if(y2 > y1)
        {
            ans = ((x == x1) &&( y >= y1 && y <= y2));
        }
        else
        {
            ans = ((x == x1) &&( y >= y2 && y <= y1 ));
        }      
    } 
    return ans;
}

/** 
 * @brief 二维矩形
 */
class Rectangle2D: public Domain<2>
{
public:
    /**
     * @brief 默认构造函数。
     *
     */
    Rectangle2D() = default;
    /**
     * @brief 默认析构函数。
     */
    ~Rectangle2D() = default;
    /**
     * @brief 含参构造函数
     * 
     * @param pointList 定义域边界的顶点，以逆时针顺序给出
     */
    Rectangle2D(std::vector<Point<2>>& _vertexList)
	{
	    assert(_vertexList.size() == 4);
	    vertexList.resize(_vertexList.size());
	    copy(_vertexList.begin(),_vertexList.end(),vertexList.begin());
	};
    /**
     * @brief 设置定义域边界的顶点
     * 
     * @param _vertexList 定义域边界的顶点，以逆时针顺序给出
     */
    virtual void setVertexList(std::vector<Point<2>>& _vertexList)
	{
	    assert(_vertexList.size() == 4);
	    vertexList.resize(_vertexList.size());
	    copy(_vertexList.begin(),_vertexList.end(),vertexList.begin());
	};
    virtual vector<Point<2>>& getVertexList(){
	return vertexList;
    }
    virtual void setVertex(int _i, const Point<2>& _vertex){
	vertexList[_i] = _vertex;
    }

    /**
     * @brief 获取定义域边界第i个顶点
     * 
     * @param _i 以逆时针顺序，顶点的下标
     * @return 第i个顶点
     */
    virtual Point<2>& getVertex(int _i)
	{
	    return vertexList[_i];
	};
    /** 
     * 
     * 
     * 
     * @return 返回所有边界
     */
    std::vector<Boundary<2>> boundary(){
	std::vector<Boundary<2>> temp;
    
	for(int i = 0;i < 3;i++)
	{
	    std::vector<Point<2>> p;
	    p.push_back(vertexList[i]);
	    p.push_back(vertexList[i+1]);
	    Boundary<2> b(p);
	    temp.push_back(b);
	}
	std::vector<Point<2>> p4(2);
	p4[0] = vertexList[3];
	p4[1] = vertexList[0];
	temp.push_back(p4);
	return temp;
    }
};

#else
#endif
